迎來 30 天鐵人挑戰的最終篇章!將 Day 28 封裝的 eye_strain_ensemble_pipeline.joblib 與 Day 29 的即時推論邏輯,串接為具備臨床眼科質感的 互動式 Web 儀表板(Web UI Dashboard)。使用者可透過直覺的滑桿與選單輸入日常生理作息,系統即時計算 CESI 綜合疲勞指數、輸出三分類機率圖卡與動態門檻警示,並附上微觀 SHAP 處方建議。文末進行 30 天從資料清洗、統計檢定、模型迭代到生產部署的完整工程架構總回顧。
一、 實作前情境:讓機器學習走出終端機,打造臨床級友善介面
在過去 29 天中,我們完成了從底層數據挖掘到高併發 API 的所有工作:
最後一哩路(The Last Mile of Data Science):
a.醫療或健康管理專家無法直接閱讀終端機印出的 JSON 字典物件。
b.一個合格的健康評估系統,必須具備:
2.快速原型框架選擇(Gradio):
二、 撰寫 Gradio 互動式用眼疲勞健康診斷儀表板
在 Colab 中新增儲存格,安裝套件並啟動完整的前端 Web 應用:
# ==========================================
# Day 30:用眼疲勞風險即時評估互動儀表板 (Gradio)
# ==========================================
import warnings
warnings.filterwarnings('ignore')
!pip install gradio -q
import gradio as gr
import pandas as pd
import numpy as np
import joblib
# 1. 載入 Day 28 持久化模型包
MODEL_FILE = 'eye_strain_ensemble_pipeline.joblib'
try:
package = joblib.load(MODEL_FILE)
pipeline = package['pipeline']
th_high = package['optimal_threshold_high']
target_names = package['target_names']
print(f"成功加載模型包!高風險動態判定門檻為: {th_high:.3f}")
except Exception as e:
raise RuntimeError(f"載入模型失敗,請確認檔案是否存在: {e}")
# 2. 定義核心預測與處方生成函數
def diagnose_eye_strain(
age, role, daily_screen_hours, sleep_hours,
break_frequency, eye_dryness, eye_pain,
headache_freq, blue_light_filter, blurred_vision
):
# 建立輸入資料 DataFrame (完全符合 Pipeline 原始輸入規格)
input_df = pd.DataFrame([{
'Age': int(age),
'Role': role,
'Daily_Screen_Hours': float(daily_screen_hours),
'Sleep_Hours': float(sleep_hours),
'Break_Frequency_Per_Hour': int(break_frequency),
'Eye_Dryness_Level': int(eye_dryness),
'Eye_Pain_Level': int(eye_pain),
'Headache_Frequency_Per_Week': int(headache_freq),
'Blue_Light_Filter_Used': blue_light_filter,
'Blurred_Vision': blurred_vision
}])
# 透過端到端管線執行即時推論
prob = pipeline.predict_proba(input_df)[0]
prob_low, prob_med, prob_high = prob[0], prob[1], prob[2]
# 計算即時 CESI 指數 (Day 15 公式)
safe_sleep = max(float(sleep_hours), 0.5)
cesi_val = (float(daily_screen_hours) / safe_sleep) * (int(eye_pain) + int(eye_dryness) + 1.0)
# 套用 Day 27 動態門檻判定規則
if prob_high >= th_high:
final_level = "高度風險 (High)"
alert_badge = "⚠️ 【臨床警示】高度眼部疲勞風險!建議就診或強制休息!"
box_style = "error"
else:
final_idx = int(np.argmax(prob[:2]))
final_level = target_names[final_idx]
if final_idx == 1:
alert_badge = "🟡 【注意預防】中度用眼疲勞,需調整用眼習慣。"
box_style = "warning"
else:
alert_badge = "🟢 【狀態良好】低度用眼疲勞,請繼續保持健康習慣。"
box_style = "info"
# 機率字典 (供 Gradio Label 元件繪製長條圖)
prob_dict = {
"低度風險 (Low)": float(prob_low),
"中度風險 (Medium)": float(prob_med),
"高度風險 (High)": float(prob_high)
}
# 生成臨床個人化白話處方箋
prescription = f"""
### 📋 臨床用眼健康診斷報告
* **綜合判定結果**:**{final_level}**
* **CESI 綜合疲勞指數**:**{cesi_val:.2f}**(母體平均參考基準線約為 25.0)
* **高風險觸發門檻**:{th_high*100:.1f}%(目前個案高風險機率:{prob_high*100:.1f}%)
---
#### 🩺 個人化生活型態衛教建議:
"""
if daily_screen_hours >= 9.0:
prescription += f"• **高暴露預警**:每日螢幕使用高達 {daily_screen_hours} 小時,已達重度暴露標準,建議每小時嚴格執行「20-20-20」遠眺放鬆。\n"
if sleep_hours <= 5.5:
prescription += f"• **修復不足預警**:每日睡眠僅 {sleep_hours} 小時,嚴重削弱眼表上皮細胞夜間修復力,此為推升風險的重要隱形推手。\n"
if blurred_vision == "Yes":
prescription += "• **急性徵兆預警**:近期出現視力模糊症狀,可能為睫狀肌痙攣或淚膜破裂,建議優先安排眼科驗光與角膜檢查。\n"
if blue_light_filter == "Yes":
prescription += "• **衛教提醒**:雖有使用抗藍光濾鏡,但根據本專案實證研究,濾鏡無法抵消長時間暴露與睡眠缺乏帶來的實質損害,請勿產生「代償性放鬆」。\n"
return alert_badge, prob_dict, prescription
# 3. 建立 Gradio UI 佈局
with gr.Blocks(title="數位用眼疲勞風險即時評估系統", theme=gr.themes.Soft()) as demo:
gr.Markdown(
"""
# 👁️ 數位用眼疲勞(Digital Eye Strain)智慧評估系統
### 30 天鐵人挑戰成果:結合 LightGBM & Random Forest 軟投票集成模型與 XAI 臨床可解釋性
"""
)
with gr.Row():
# 左側輸入控制面板
with gr.Column(scale=1):
gr.Markdown("### 👤 受試者基本作息與自覺症狀輸入")
age = gr.Slider(minimum=18, maximum=75, value=24, step=1, label="年齡 (Age)")
role = gr.Dropdown(choices=["Student", "Non-Student"], value="Student", label="身分角色 (Role)")
daily_screen = gr.Slider(minimum=1.0, maximum=18.0, value=11.5, step=0.5, label="每日螢幕時數 (小時)")
sleep_hours = gr.Slider(minimum=2.0, maximum=12.0, value=5.0, step=0.5, label="每日睡眠時數 (小時)")
break_freq = gr.Slider(minimum=0, maximum=10, value=1, step=1, label="每小時休息次數 (次/小時)")
with gr.Row():
eye_dryness = gr.Slider(minimum=0, maximum=10, value=8, step=1, label="眼睛乾澀自覺分數 (0-10)")
eye_pain = gr.Slider(minimum=0, maximum=10, value=7, step=1, label="眼睛疼痛自覺分數 (0-10)")
headache_freq = gr.Slider(minimum=0, maximum=7, value=4, step=1, label="每週頭痛次數 (天/週)")
with gr.Row():
blue_filter = gr.Radio(choices=["Yes", "No"], value="Yes", label="使用抗藍光濾鏡")
blurred = gr.Radio(choices=["Yes", "No"], value="Yes", label="近期視力模糊")
btn_submit = gr.Button("🔍 立即進行智慧風險評估", variant="primary")
# 右側結果與報告展示面板
with gr.Column(scale=1):
gr.Markdown("### 📊 智慧推論診斷結果")
out_badge = gr.Textbox(label="系統診斷判定狀態", interactive=False)
out_chart = gr.Label(num_top_classes=3, label="三類別預測機率分佈 (Soft Voting Probabilities)")
out_report = gr.Markdown(label="個人化衛教處方箋")
# 綁定按鈕事件
btn_submit.click(
fn=diagnose_eye_strain,
inputs=[
age, role, daily_screen, sleep_hours,
break_freq, eye_dryness, eye_pain,
headache_freq, blue_filter, blurred
],
outputs=[out_badge, out_chart, out_report]
)
# 4. 啟動 Web 服務
demo.launch(share=True, debug=False)



立即進行智慧風險評估:

三、 圖表解讀與客觀數據分析
本實作以 Gradio 互動式 Web 儀表板成功串接已持久化的軟投票集成模型(eye_strain_ensemble_pipeline.joblib),在點擊「立即進行智慧風險評估」後,前端即時呈現了診斷燈號、三類別預測機率條形圖與臨床個人化衛教處方箋。從輸出的介面數值中,可提煉出三項關鍵的落地實證成果:
1.即時推論機率與動態門檻機制在前端的完美復現
a.軟投票機率分佈條形圖:
b.臨床衛教處方箋的動態生成(結合 XAI 與統計實證):